<template>
  <el-form :model="formData" ref="formRef" v-bind="{ ...attrs }">
    <el-row :gutter="props.gutter">
      <el-col
        v-for="(form, index) in props.forms"
        :key="form.prop"
        :span="form.span || 24"
        :class="form.class"
        v-show="!form.hidden"
      >
        <el-form-item
          :key="index"
          :prop="form.prop"
          v-if="!form.hidden"
          :label="form.label"
          :rules="form.rules || []"
          v-bind="{ ...form }"
        >
          <template #label>
            <div v-if="form.slotHeaderName" class="slotHeaderName">
              <slot :name="form.slotHeaderName" :params="params" :form="form" />
            </div>
          </template>
          <template v-if="form.slotName">
            <slot :name="form.slotName" :params="props.params" :form="form" />
          </template>
          <template v-else>
            <div v-if="form.itemType === 'span'" v-bind="{ ...form }">
              <div>
                {{ params[form.prop] ? params[form.prop] : "-" }}
              </div>
            </div>
            <div v-if="form.itemType === 'image'">
              <el-image :src="params[form.prop]" v-bind="{ ...form }">
                <template #progress="{ activeIndex, total }">
                  <span>{{ activeIndex + 1 + "-" + total }}</span>
                </template>
              </el-image>
            </div>
            <div v-if="form.itemType === 'selectLabel'">
              <div class="text-[1C174D]">
                {{ params[form.prop] ? mapSelectLabel(form.options, params[form.prop]) : "-" }}
              </div>
            </div>
            <div v-if="form.itemType === 'dateLabel'">
              <div>{{ params[form.startProp] }}~{{ params[form.endProp] }}</div>
            </div>
            <div v-if="form.itemType === 'checkboxLabel'">
              {{ mapCheckboxLabel(form.options, params[form.prop]) }}
            </div>
            <div v-if="form.itemType === 'uploadLabel'">
              <div v-if="isString(params[form.prop])">
                <el-image
                  :src="params[form.prop]"
                  style="border: 1px solid #e5e5e5; border-radius: 10px; overflow: hidden"
                  :style="form.style ? form.style : { width: '120px', height: '120px' }"
                  :preview-src-list="[params[form.prop]]"
                  v-bind="{ ...form }"
                >
                  <template #progress="{ activeIndex, total }">
                    <span>{{ activeIndex + 1 + "-" + total }}</span>
                  </template>
                </el-image>
              </div>
              <div v-if="isArray(params[form.prop])">
                <el-image
                  v-for="(item, imageIndex) in params[form.prop]"
                  :src="item.url || item.contractFileUrl"
                  style="
                    width: 100px;
                    height: 100px;
                    margin-right: 10px;
                    border: 1px solid #e5e5e5;
                    border-radius: 10px;
                    overflow: hidden;
                  "
                  :preview-src-list="[item.url || item.contractFileUrl]"
                  :key="imageIndex"
                >
                </el-image>
              </div>
            </div>
            <div class="cascader-label w-full" v-if="form.itemType === 'cascaderLabel'">
              <el-cascader
                v-model="formData[form.prop]"
                :clearable="form.clearable || true"
                :filterable="form.filterable || true"
                :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
                @change="value => handleCascaderChange(value, form)"
                v-bind="form"
              >
              </el-cascader>
            </div>
            <el-input
              v-if="form.itemType === 'input' || form.itemType === undefined"
              v-model="formData[form.prop]"
              :clearable="form.clearable || true"
              :maxlength="30"
              :placeholder="form.placeholder || '请输入'"
              :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
              :show-word-limit="true"
              v-bind="{ ...form }"
            >
              <template #append v-if="form.append">
                <div
                  @click="
                    () => {
                      onAppendInput(form);
                    }
                  "
                >
                  {{ form.append }}
                </div>
              </template>
            </el-input>
            <el-input
              v-if="form.itemType === 'textarea'"
              v-model="formData[form.prop]"
              :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
              type="textarea"
              :maxlength="300"
              :rows="4"
              :show-word-limit="true"
              v-bind="{ ...form }"
            >
            </el-input>
            <el-select
              v-else-if="form.itemType === 'select'"
              v-model="formData[form.prop]"
              :clearable="form.clearable || true"
              :filterable="form.filterable || true"
              :placeholder="form.placeholder || '请选择'"
              :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
              v-bind="{ ...form }"
              @change="
                value => {
                  handleSelectChange(value, form);
                }
              "
            >
              <el-option
                v-for="(option, selectIndex) in form.options"
                :key="selectIndex + option.value"
                :value="option.value"
                :label="option.label"
                v-bind="{ ...option }"
                @click="
                  value => {
                    form.clickSelect ? form.clickSelect({ value: option.value, form, index }) : '';
                  }
                "
              >
              </el-option>
              <slot :name="form.selectOptionSlotName" :params="form.params" :form="form"></slot>
            </el-select>
            <el-cascader
              v-else-if="form.itemType === 'cascader'"
              v-model="formData[form.prop]"
              :clearable="form.clearable || true"
              :filterable="form.filterable || true"
              :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
              @change="value => handleCascaderChange(value, form)"
              v-bind="form"
            >
            </el-cascader>
            <el-switch
              v-else-if="form.itemType === 'switch'"
              v-model="formData[form.prop]"
              :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
              v-bind="{ ...form }"
            ></el-switch>
            <el-slider
              v-else-if="form.itemType === 'slider'"
              v-model="formData[form.prop]"
              :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
              v-bind="{ ...form }"
            ></el-slider>
            <el-date-picker
              v-else-if="form.itemType === 'date'"
              v-model="formData[form.prop]"
              v-bind="{ ...form }"
              :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
            ></el-date-picker>
            <el-time-picker
              v-else-if="form.itemType === 'time'"
              v-model="formData[form.prop]"
              v-bind="{ ...form }"
              :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
            ></el-time-picker>
            <el-transfer
              v-else-if="form.itemType === 'transfer'"
              v-model="formData[form.prop]"
              :data="form.options"
              v-bind="{ ...form }"
              :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
            >
            </el-transfer>
            <el-radio-group
              v-else-if="form.itemType === 'radio'"
              v-model="formData[form.prop]"
              v-bind="{ ...form }"
              :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
            >
              <el-radio v-for="(radio, radioIndex) in form.options" :label="radio.value" :key="radioIndex">
                {{ radio.label }}
              </el-radio>
            </el-radio-group>
            <div v-else-if="form.itemType === 'checkbox'">
              <el-checkbox
                v-model="checkAll"
                :indeterminate="isIndeterminate"
                @change="handleCheckAllChange"
                v-if="props.isCheckedAll"
              >
                全部
              </el-checkbox>
              <el-checkbox-group
                v-model="formData[form.prop]"
                v-bind="{ ...form }"
                :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
                @change="
                  value => {
                    handleCheckBoxChange(value, form);
                  }
                "
              >
                <el-checkbox
                  v-for="(checkbox, checkboxIndex) in form.options"
                  :label="checkbox.value"
                  :key="checkbox.value + checkboxIndex"
                  name="type"
                >
                  {{ checkbox.label }}
                </el-checkbox>
              </el-checkbox-group>
            </div>
            <el-upload
              v-else-if="form.itemType === 'upload'"
              v-model:file-list="formData[form.prop]"
              class="upload-container"
              :auto-upload="true"
              :on-preview="handlePictureCardPreview"
              :before-upload="
                file => {
                  handleBeforeUpload(file, form);
                }
              "
              :on-progress="
                file => {
                  console.log(file);
                }
              "
              :on-remove="
                (file, fileList) => {
                  handleRemove(file, fileList, form);
                }
              "
              :on-change="
                (file, fileList) => {
                  handleUploadChange(file, fileList, params, form);
                }
              "
              list-type="picture-card"
              :drag="true"
              action="https://test-gateway-middleend.qingyunzu.com/assets-ms/file/upload"
              v-bind="form"
            >
              <div class="text-center">
                <div>
                  <CardSvg :svg-type="form.svgType ? form.svgType : 1"></CardSvg>
                </div>
              </div>
              <template #tip v-if="form.tip ? form.tip : false">
                <div class="text-[#6B678E] text-14px">
                  {{ form.tip }}
                </div>
              </template>
            </el-upload>
            <div v-else-if="form.itemType === 'button'" v-bind="{ ...form }" style="display: flex">
              <el-button
                v-for="(buttonItem, buttonIndex) in form.options"
                :key="buttonItem.id"
                :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
                v-bind="{ ...buttonItem }"
                @click="form.click ? form.click(buttonItem) : onButtonClick(formRef, params, buttonIndex, buttonItem)"
              >
                {{ buttonItem.label }}
              </el-button>
            </div>
            <div v-else-if="form.itemType === 'fixedButton'" v-bind="{ ...form }" class="flex fixed bottom-10px">
              <el-button
                v-for="(buttonItem, buttonIndex) in form.options"
                :key="buttonItem.id"
                :style="form.itemWidth ? `width: ${form.itemWidth}` : 'width:100%'"
                v-bind="{ ...buttonItem }"
                @click="onButtonClick(formRef, params, buttonIndex, buttonItem)"
              >
                {{ buttonItem.label }}
              </el-button>
            </div>
          </template>
        </el-form-item>
      </el-col>
      <el-col :span="24" class="center" v-if="props.buttonConfig.showSubmitButton">
        <el-form-item label="" label-width="0" class="dialog-footer">
          <el-button
            v-for="(buttonItem, buttonIndex) in props.buttonConfig.options"
            :key="buttonItem.id"
            v-bind="{ ...buttonItem }"
            @click="onButtonClick(formRef, buttonIndex, buttonItem)"
          >
            {{ buttonItem.label }}
          </el-button>
        </el-form-item>
      </el-col>
      <el-dialog v-model="dialogVisible">
        <div class="text-center">
          <el-image w-full :src="dialogImageUrl" alt="Preview Image" />
        </div>
      </el-dialog>
    </el-row>
  </el-form>
</template>

<script setup>
  import { isString, isArray } from "lodash";
  import CardSvg from "../CardSvg/index.vue";
  import { defineProps, defineEmits, ref, useAttrs, defineExpose, watch, onMounted } from "vue";
  import { ElMessage } from "element-plus";

  const checkAll = ref(false);
  const isIndeterminate = ref(true);
  const formRef = ref(null);
  const attrs = useAttrs(); //外部传进的额外属性
  const props = defineProps({
    forms: {
      type: Array,
      default: () => [],
    },
    params: {
      type: Object,
      default: () => ({}),
    },
    gutter: {
      type: Number,
      default: 10,
    },
    buttonConfig: {
      type: Object,
      default: () => ({
        showSubmitButton: false,
        submitText: "提交",
        resetText: "重置",
      }),
    },
    loadMoreNameData: {
      type: Function,
      default: () => {
        return () => {};
      },
    },
    isCheckedAll: {
      type: Boolean,
      default: false,
    },
  });
  let formData = ref({ ...props.params }); //表单提交参数

  const dialogImageUrl = ref("");
  const dialogVisible = ref(false);

  const handleCascaderChange = (value, form) => {
    console.log(value, form);
    emits("handleCascaderChange", { value, form });
  };

  const handleSelectChange = (value, form) => {
    emits("handleSelectChange", { value, form });
  };

  //图片尺寸检验
  const validImageSize = (file, imgWidth, imgHeight) => {
    let img = new Image();
    let _URL = window.URL || window.webkitURL;
    new Promise((resolve, reject) => {
      img.onload = function () {
        let valid = img.width >= imgWidth && img.height >= imgHeight;
        valid ? resolve() : reject();
      };
      img.src = _URL.createObjectURL(file);
    })
      .then(() => {
        return file;
      })
      .catch(() => {
        ElMessage.error(`图片尺寸需要大于${imgWidth}*${imgHeight}，请重新上传`);
        return false;
      });
  };
  const handleBeforeUpload = (file, form) => {
    if (form.prop == "customerLogo") {
      const typeList = ["jpg", "jpeg", "png", "gif"];
      let fileType = file.name.split(".").slice(-1)[0].toLowerCase();
      if (typeList.indexOf(fileType) === -1) {
        ElMessage.error("图片格式只能为jpg/jpeg/png/gif");
        return false;
      }
      const isLt2M = file.size / 1024 / 1024 < 10;
      if (!isLt2M) {
        ElMessage.error("上传图片大小不能超过 10MB!");
        return false;
      }
      validImageSize(file, 700, 700);
    }

    emits("handleBeforeUpload", {
      file,
      form,
    });
  };

  const handleCheckBoxChange = (value, form) => {
    emits("handleCheckBoxChange", {
      value,
      form,
    });
  };

  //图片成功上传回调
  const handlePictureCardPreview = uploadFile => {
    dialogImageUrl.value = uploadFile.url;
    dialogVisible.value = true;
  };

  //upload移除图片
  const handleRemove = (uploadFile, uploadFiles, form) => {
    emits("handleRemove", {
      uploadFile,
      uploadFiles,
      form,
    });
  };

  //映射selet中的label值
  const mapSelectLabel = (options = [], value = "") => {
    if (!options) {
      return "";
    }
    if (!value) {
      return "";
    }
    if (options && options.length && value) {
      const item = options.find(item => item.value == value);
      if (item) {
        return item.label;
      }
    }
  };

  //映射checkbox的值
  const mapCheckboxLabel = (options = [], value = []) => {
    let labels = [];
    if (!options) {
      return "";
    }
    if (!value) {
      return "";
    }
    if (options && options.length && value && value.length) {
      options.forEach(item => {
        if (!value.includes(item.value)) {
          return;
        }
        labels.push(item.label);
      });
    }
    if (typeof labels !== "string") {
      labels = labels.join("、");
    }
    return labels;
  };
  //图片上传的change时间
  const handleUploadChange = (file, fileList, params, form) => {
    const formData = new FormData();
    fileList.forEach(item => {
      formData.append("file", item.raw);
    });
    formData.append("fileType", "2"); //文件类型,01-图片,02-文件,03-视频
    formData.append("isSecretFile", "true"); //是否私密文件

    Api.customer.FileUpload(formData).then(res => {
      if (res.code == 200) {
        file.url = res.data;
        file.contractFileUrl = res.data;
        file.contractFileName = file.name;
        let index = file.name.indexOf(".");
        let contractFileType = file.name.substring(index + 1);
        file.contractFileType = contractFileType;
        emits("handleUploadChange", {
          form,
          params,
          url: res.data,
          fileList,
        });
      }
    });
  };
  //input框后缀点击时间
  const onAppendInput = form => {
    emits("onAppendInput", form);
  };

  const emits = defineEmits([
    "onSubmit",
    "onReset",
    "onOther",
    "handleCheckAllChange",
    "update:modelValue",
    "onAppendInput",
    "handleUploadChange",
    "handleRemove",
    "handleBeforeUpload",
    "handleCheckBoxChange",
    "handleSelectChange",
    "handleCascaderChange",
  ]);

  // 提交按钮点击事件
  const onButtonClick = async (formEl, params, index, buttonItem) => {
    if (buttonItem.id === 1) {
      if (!formEl) return;
      await formEl.validate((valid, fields) => {
        if (valid) {
          emits("onSubmit", {
            params,
            index,
            buttonItem,
          });
        } else {
          console.log("error submit!", fields);
        }
      });
    } else if (buttonItem.id === 0) {
      if (!formEl) return;
      formEl.resetFields();
      emits("onReset", {
        params,
        index,
        buttonItem,
      });
    } else {
      //@ts-ignore
      await formEl.validate((valid, fields) => {
        if (valid) {
          emits("onOther", {
            params,
            index,
            buttonItem,
          });
        } else {
          console.log("error submit!", fields);
        }
      });
      // ElMessage.warning('请检查按钮的id设置,1为提交，0为重置')
    }
  };
  //全选点击事件
  const handleCheckAllChange = value => {
    console.log(value);
    emits("handleCheckAllChange", { value: checkAll.value });
    isIndeterminate.value = false;
  };

  onMounted(() => {
    // formData=props.params
  });
  //监听props.params
  watch(
    () => props.params,
    newValue => {
      if (newValue) {
        formData.value = newValue;
        // console.log(formData,'fromData')
      }
    },
    {
      deep: true,
      immediate: true,
    }
  );

  defineExpose({
    onButtonClick,
    formRef,
    checkAll,
    isIndeterminate,
    formData,
  });
</script>
<style lang="scss" scoped>
  .center {
    display: flex;
    justify-content: center;
  }

  .dialog-footer {
    text-align: center;
    padding-top: 20px;
    margin-bottom: 0px;
  }

  :deep(.el-upload) {
    border: 1px dashed #ecebf1;
    background: #fff;
  }

  :deep(.card-upload .el-upload) {
    width: 250px;
    height: 160px;
  }

  :deep(.card-upload .el-upload-dragger) {
    padding: 0;
  }

  :deep(.el-input-group__append) {
    background: #fff;
    box-shadow: none;
    color: var(--bd);
    cursor: pointer;
  }

  :deep(.el-label .el-form-item__label) {
    color: #6b678e;
  }

  .cascader-label {
    :deep(.el-input__inner) {
      border: 1px solid #fff;
      -webkit-text-fill-color: var(--el-text-color-primary) !important;
    }
    :deep(.el-input__wrapper) {
      background-color: #fff;
      padding: 0 !important;

      // border-color: transparent !important;
      /* 使用 !important 确保优先级 */
    }
    :deep(.el-input__suffix) {
      display: none;
    }
  }
</style>
